#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<unistd.h>

 #include <sys/types.h>
#include <sys/wait.h>

extern char**environ;

using namespace std;

const int maxsize=1024;

//获取命令提示:
char comandInfo[maxsize];
int comandInfoSize=0;

//获取命令
char getComand[maxsize];
//处理后的命令
char *gargv[64];
int gargc=0;

//获取shell的pwd
char pwd[maxsize];
//更新pwdenv
char pwdenv[maxsize];
//为子进程创建环境变量
char *env[64];


//重定向枚举
enum redirect{
    infile=1,
    outfile,
    appfile
};

//重定向x定i
#define ISSPACE(x) do {\
      while(isspace(*x)){\
        x++;}\
}while(0)

//重定向文件名字
char *filename=nullptr;
int filecount=0;


string getNAME()
{
    string name=getenv("USER");
    if(name.empty())
    {
        return "NONE";   
    }
    return name;
}

string getHOSTNAME()
{
    string hostname=getenv("HOSTNAME");
    if(hostname.empty())
    {
        return "NONE";
    }
    return hostname ;
}

string getPWD()
{
    getcwd(pwd,sizeof(pwd));
    snprintf(pwdenv,sizeof(pwdenv),"PWD=%s",pwd);
    putenv(pwdenv);
    return pwd;
}


 string MakeComandInfo()
 {
    snprintf(comandInfo,maxsize,"[%s@%s %s]*",getNAME().c_str(),getHOSTNAME().c_str(),getPWD().c_str());
    return comandInfo;
 }


void  printComandInfo()//打印命令提示
{
    memset(comandInfo,0,sizeof(comandInfo));
    printf("%s",MakeComandInfo().c_str());
    fflush(stdout);
}



bool GetComand()
{
    char*str= fgets(getComand,maxsize,stdin); 
    if(str==NULL)
        return false;
    getComand[strlen(getComand)-1]=0;
   // cout<<str;
    return true;
}


void handredirect(char str[],int size)
{
    size--;
    while(size>=0)
    {
        if(str[size]=='>'&&size!=0)
        {
            if(str[size-1]=='>'&&size>=1)
            {
                filename=str+size+1;
                getComand[size-1]=0;
                ISSPACE(filename);
                filecount=appfile;
                return ;
            }
            else
            {
                filename=str+size+1;
                getComand[size]=0;
                ISSPACE(filename);
                filecount=outfile;
                return;
            }
        }
        else if(str[size]=='<'&&size!=0)
        {
                filename=str+size+1;
                getComand[size]=0;
                ISSPACE(filename);
                filecount=infile;
                return;
        }
        else 
            size--;
    }
}

void  HandComand()
{
    gargc=0;
    filecount=0;
    filename=nullptr;
    memset(gargv,0,sizeof(gargv)); 
    handredirect(getComand,strlen(getComand));
    char buff[]=" ";
    gargv[gargc++]= strtok(getComand,buff);
    while(gargv[gargc++]=strtok(NULL,buff)); 
    gargc--;       
}           
            
bool debug()
{
    //printf("%d\n",strlen(env[1]));
    cout<<"debug"<<endl;
    cout<<gargc<<endl;
    if(filename)
    {
        cout<<"定向数据:"<<getComand<<" ";
        cout<<"文件名称:"<<filename<<":";
        cout<<"重定向为:" <<filecount<<endl;
        return true;
    }
    return false;
}



void MyShell()
{
 //   if(filecount!=0)
 //    {
 //       cout<<filecount<<endl;
 //        exit(2);
 //    }
 //  else  
    
    //bin cout<<gargc<<endl;
    // argv[gargc][strlen(gargv[gargc])]=' ';
     execvp(gargv[0],gargv);
     exit(0);
}

void run()
{
    pid_t id=fork();
    if(id==0)
    {
        MyShell();
        exit(1);
    }
    else if(id>0)
    {
        int status=0;
        pid_t cid=waitpid(id,&status,0);
    }
}

bool CheckBiuldComand()
{
    if(strcmp("cd",gargv[0])==0)
    {
        if(gargc==2)
        {
            for(int i=0;environ[i];i++)
                if(strncmp(environ[i],"PWD",3)==0)
                    cout<<environ[i]<<endl;
            chdir(gargv[1]);
        }
        return true;
    }
    else if(strcmp(gargv[0],"env"))
    {
        if(gargc==1)
        {
            for(int i=0;environ[i];i++)
            {
                cout<<environ[i]<<endl;
            }
        }
        return true;
    }
    return false;
}

void debugargv()
{
    for(int i=0;gargv[i];i++)
    {
        printf("garv%d:%s\n",i,gargv[i]);
    }
}


void Initenv()
{
    int i;
    for(i=0;environ[i];i++)
    {
        //cout<<environ[i]<<endl;
        env[i]=(char*)malloc(strlen(environ[i]+1));
        strncpy(env[i],environ[i],strlen(environ[i]));
    }
    env[i]=nullptr;
}
int main()
{
    
    while(1)
    {
        Initenv();
         printComandInfo(); //打印命令提示
       // MakeComandInfo();
        if( GetComand()==false) continue; //获取用户输入信 
        
    
      HandComand();  //分析命令
      //varif(debug()) continue; 
        debugargv(); 
      if(CheckBiuldComand()) continue; //判断是否为内建命令
      run(); //执行命令 
    }
      return 0;
}
